import classNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import { Select } from '../select';

export type OptionValues = string | number | boolean;

export interface ISelectedData {
  // value?: OptionValues | OptionValues [] | string[] | number | number[] | boolean;
  value?: OptionValues; // 作为key 来使用 string
  label?: string;
}

export interface IGangedSelectProps {
  titles?: ISelectedData[];
  defaultValues?: ISelectedData[];
  values?: ISelectedData[][];
  loadData?: (depth: number, id?: OptionValues | null) => Promise<ISelectedData[]>; // 加载数据的方法
  onSelect?: (values: ISelectedData[]) => void; // 选中后返回数据
  searchable?: boolean;
  className?: string;
  style?: React.CSSProperties;
}

export class GangedSelect extends React.Component<IGangedSelectProps, any> {
  public static defaultProps = {
    titles: [{ value: '0', label: '省份' }, { value: '0-0', label: '城市' }],
  };

  public static propTypes = {
    searchable: PropTypes.bool,
    className: PropTypes.string,
    style: PropTypes.object,
  };

  constructor(props: IGangedSelectProps) {
    super(props);
    this.state = {
      values: props.defaultValues || props.titles || [], // 选中的数据
      options: props.values || [[], [], []], // 级联数据源
    };
    this.handleChange = this.handleChange.bind(this);
  }

  public componentDidMount() {
    if (!this.props.loadData) {
      return;
    }
    // 组件挂载就加载 第一联的数据
    this.props.loadData(0)
      .then((data) => {
        const mapOptions = [...this.state.options];
        mapOptions[0] = data;
        this.setState({
          options: mapOptions,
        });
      }).catch((e) => {
        // tslint:disable-next-line
        console.error('级联获取数据失败', e);
      });
  }

  // 选择某项后更新数据 values, options
  public updateSelectedOptions(
    values: ISelectedData[],
    index: number,
    option: ISelectedData | null) {
    const selectCount = (this.props.titles && this.props.titles.length) || 2;
    // 最多三级 到了倒数第二级 就不去加载数据
    if (!this.props.loadData || index >= selectCount - 1) {
      if (this.props.onSelect) {
        this.props.onSelect(values);
      }
      this.setState({
        values,
      });
      return;
    }
    // 选择后直接更新下一级的数据
    const value = option && option.value;
    const selectIndex = index + 1;
    this.props.loadData(selectIndex, value)
      .then((data) => {
        const mapOptions = [...this.state.options];
        mapOptions[selectIndex] = data;
        if (this.props.onSelect) {
          this.props.onSelect(values);
        }
        this.setState({
          values,
          options: mapOptions,
        });
      }).catch((e) => {
        // tslint:disable-next-line
        console.error('级联获取数据失败', e);
      });
  }

  public handleFocus(event: React.FocusEvent<Element>, index: number) {
    if (!this.state.options[index].length) {
      const parentOption = this.state.values[index - 1];
      if (this.props.loadData && parentOption) {
        this.props.loadData(index - 1, parentOption.value)
          .then((data) => {
            const mapOptions = [...this.state.options];
            mapOptions[index] = data;
            this.setState({
              options: mapOptions,
            });
          });
      }
    }
  }

  public handleChange(option: ISelectedData | ISelectedData[] | null, index: number) {
    // 当option是一个数组 返回默认的值
    if (option && option instanceof Array) {
      if (this.props.onSelect) {
        this.props.onSelect(this.state.values);
      }
      return;
    }

    // 当选择联的值 和上一次相同时候直接返回
    if (option && option.value && this.state.values[index].value === option.value) {
      if (this.props.onSelect) {
        this.props.onSelect(this.state.values);
      }
      return;
    }

    // 判断选择的是第几联 并更新对应的数据
    const initValues = this.props.titles || [];
    let mapValues = [...initValues];
    switch (index) {
      case 0:
        mapValues = [...initValues];
        mapValues[index] = option || {};
        this.updateSelectedOptions(mapValues, index, option);
        return;
      case 1:
        mapValues = [...this.state.values];
        mapValues[index] = option || {};
        if (mapValues[2]) {
          mapValues[2] = initValues[2];
        }
        this.updateSelectedOptions(mapValues, index, option);
        return;
      case 2:
        mapValues = [...this.state.values];
        mapValues[index] = option || {};
        this.updateSelectedOptions(mapValues, index, option);
        return;
    }
  }

  public render() {
    const props = this.props;
    const depth = props.titles && props.titles.length || 0;
    return (
      <div className={classNames('br-ganged-select', props.className)} style={props.style}>
        {
          props.titles && props.titles.map((item, index) => {
            const className = `br-ganged-select__depth-${depth} select${index}`;
            return <div className={className} key={item.label}>
              <Select type={this.props.searchable ? `search` : ''}
                value={this.state.values[index]}
                options={this.state.options[index]}
                onChange={(selectedOption) => this.handleChange(selectedOption, index)}
                onFocus={(event) => this.handleFocus(event, index)}
                emptyTips={<div style={{ margin: '5px 0' }} className="text text-help align-center">加载中...</div>}
              />
            </div>;
          })
        }
      </div>
    );
  }
}
